import React, { Component } from 'react';
import Map from './Map';
import Inventory from './Inventory';
import Status from './Status';
// import $ from 'jquery';
// const SockJS = window.SockJS;
// const WebSocket = window.WebSocket;
const swal = window.swal

export default class Game extends Component {
  constructor(props) {
    super(props)
    this.state = {
      logs: ['进入游戏'],
      showing: 0, //0是地图 1是角色状态 2 inventory
      status: {//角色状态
        name: '路过的肥宅',
        power: 5,
        level: 1,
        exp: 0,
        area_id: '',
      },
      inventory: [
        { thing_id: '1', type: 'item', num: 2 }
      ],
      detail: {//Things' detail need to request from server
        items: [{ "price": 10, "desc": "A fruit can recover HP", "id": "5bbdc2fd2eae259ff4e7e168", "name": "Apple" }],
        equips: [{ "name": "copper sword", "power": 3, "price": 10, "id": "5bbdc4332eae259ff4e7e169", "part": "weapon", "hp": 0, "desc": "A sword made by copper" }],
      },
      map: {//地图状态以及生物
        all_position: [{ name: '教堂', id: '0' }, { name: '果园', id: '1' }],
        position: { name: '教堂' },
        area: { name: '新手村' },
        lives: {
          mobs: [{ id: 0, name: '路过的新手', riskDegree: 2, power: 4 },
          { id: 1, name: '咯咯叫的母鸡', riskDegree: 2, power: 5 },
          { id: 2, name: '路过的老鼠', riskDegree: 2, power: 6 },
          { id: 3, name: '玉米', riskDegree: 4, power: 12 },],
          players: [],
        },
      },
      equiping: []
    }
  }

  componentDidMount = async () => {
    // const ws = this.props.ws

    //Mount listening function to ws
    //Update mobs info and player info
    this.mountListenFuncs(this.props.ws)
    //Mount listening function to ws

    //Get and set player
    const area_id = await this.getAndSetPlayer()
    //Get and set player

    //Refresh map info
    this.refreshMap(area_id)
    //Refresh map info

    //Request for inventory
    this.props.ws.mySend({ url: 'inventory' })

    //Request for equiping
    this.props.ws.mySend({ url: 'equiping' })
  }

  refreshPlayer = new_player => {
    //Check if level up
    const old_level = this.state.status.level
    this.setState({ status: new_player })
    console.log('old_level:' + old_level + 'new_level:' + new_player.level)
    if (old_level < new_player.level) {
      this.alert('升级了!')
    }
  }

  mountListenFuncs = ws => {
    const me = this
    ws.cbs['announce'] = (announce) => {
      me.log(announce.msg)
      if (announce.type === 'warn') {
        me.alert(announce.msg, announce.type, 'warning') //"warning"、"error"、 "success"、"info" and "question"
      }
    }
    ws.cbs['players'] = data => {
      const map = me.state.map
      map.lives.players = data.players
      me.setState({ map })
      // By the way refresh my info
      this.refreshPlayer(data.players.find(it => it.username == me.props.id))
    }
    ws.cbs['mobs'] = data => {
      const map = me.state.map
      map.lives.mobs = data.mobs
      me.setState({ map })
    }
    ws.cbs['lives'] = data => {
      const map = me.state.map
      map.lives.mobs = data.mobs
      map.lives.players = data.players
      me.setState({ map })
      // By the way refresh my info
      this.refreshPlayer(data.players.find(it => it.username == me.props.id))
    }
    ws.cbs['move'] = data => {
      if (data.ok) {
        console.log('Move successfully')
        me.refreshMap()
        // TODO: Refresh my info

      } else {
        console.log('Move fail: ' + data.err)
      }
    }
    ws.cbs['inventory'] = data => {
      //1. Refresh inventory state 2. Request if items or equips' info haven't stored else do nothing
      const inventory = data.inventory
      this.setState({ inventory })
      this.refreshThingsInfo(inventory)
    }
    ws.cbs['item'] = data => {
      //Refresh item detail
      const item = data.item
      const detail = this.state.detail
      if(detail.items.find(it => it.id == item.id) == null){
        detail.items.push(item)
      }
      this.setState({ detail })
    }
    ws.cbs['equip'] = data => {
      //Refresh equip detail
      const equip = data.equip
      const detail = this.state.detail
      if(detail.equips.find(it => it.id == equip.id) == null){
        detail.equips.push(equip)
      }
      this.setState({ detail })
    }
    ws.cbs['use_item'] = data => {
      if (data.ok) {
        this.alert('使用道具成功')
      } else {
        this.alert('使用道具失败: ' + data.err, 'warning')
      }
    }
    ws.cbs['myself'] = data => {
      me.refreshPlayer(data.player)
    }
    ws.cbs['equiping'] = data => {
      // me.refreshPlayer(data.player)
      if(data.ok = true){
        me.setState({equiping: data.equipings})
      }
    }
  }

  items = (inventory) => {
    return inventory.filter(it => it.type === 'item')
  }

  equips = (inventory) => {
    return inventory.filter(it => it.type === 'equip')
  }

  refreshThingsInfo = inventory => {
    const ws = this.props.ws
    const details = this.state.detail

    this.items(inventory).filter(item => details.items.find(it => it.id === item.thing_id) == null).map(item => {
      ws.mySend({ url: 'item', id: item.thing_id })
    })

    this.equips(inventory).filter(equip => details.equips.find(it => it.id === equip.thing_id) == null).map(equip => {
      ws.mySend({ url: 'equip', id: equip.thing_id })
    })
  }

  getAndSetAllLives = id => {
    const ws = this.props.ws
    const me = this

    //Update lives in position
    ws.mySend({ url: 'lives', id: id })
  }

  getSubPositions = (pid) => {
    const ws = this.props.ws
    const me = this
    ws.mySend({ url: 'sub_positions', pid: pid }, data => {
      const map = me.state.map
      map.all_position = data.positions
      me.setState({ map })
    })
  }

  getAndSetAreaInfo = (pid) => {
    const ws = this.props.ws
    const me = this
    ws.mySend({ url: 'position', id: pid }, data => {
      const map = me.state.map
      map.area = data
      me.setState({ map })
    })
  }

  getAndSetPosition = (area_id) => {
    const ws = this.props.ws
    const me = this
    return new Promise((resolve, reject) => {
      // const area_id = "5bad9f6fa83424ab66367262"
      ws.mySend({ url: 'position', id: area_id }, data => {
        const map = me.state.map
        map.position = data
        me.setState({ map })
        resolve(data.pid)
      })
    })
  }

  getAndSetPlayer = () => {
    const ws = this.props.ws
    const me = this
    return new Promise((resolve, reject) => {
      //TODO: update
      ws.mySend({ url: 'player', id: me.props.id }, data => {
        me.setState({ status: data.player })
        resolve(data.area_id)
      })
    })
  }


  attack = (it) => {
    const ws = this.props.ws
    const me = this
    if (it.username == null) {
      ws.mySend({ url: 'attack_mob', mob_id: it.id })
    } else {
      ws.mySend({ url: 'attack_player', player_id: it.id })
    }
  }

  refreshMap = async area_id => {
    if (area_id == null) {
      area_id = this.state.status.area_id
    }
    //Get and set position
    const pid = await this.getAndSetPosition(area_id)
    //Get and set position

    //GAS all lives in this position
    this.getAndSetAllLives(area_id)
    //GAS all lives in this position

    //Get area info
    // const pid = '5bab613b47d15a7bbc735548'
    // const pid = this.state.map.position.pid
    this.getAndSetAreaInfo(pid)
    //Get area info

    //Get sub positions
    this.getSubPositions(pid)
    //Get sub positions
  }

  log = (text) => {
    const logs = this.state.logs
    logs.push(text)
    this.setState({ logs })
  }

  alert = (text, type = null) => {
    swal({ title: text, type })
  }

  Log = (props) => {
    const last10 = this.state.logs.slice(-50, this.state.logs.length)
    const logs = last10.map(log => {
      return (<div>{log}</div>)
    })
    return (
      <div>
        <div>公告</div><br />
        <div>
          {logs}
        </div>
      </div>
    )
  }

  move = (area_id, src_area_id) => {
    const ws = this.props.ws
    const me = this

    //TODO: If player is in the area then do nothing
    ws.mySend({ url: 'move', area_id: area_id, src_area_id: src_area_id })
  }

  useThing = (type, inventoryId) => {
    if (type === 'item') {
      const ws = this.props.ws
      ws.mySend({ url: 'use_item', id: inventoryId })
    }else{
      const ws = this.props.ws
      ws.mySend({ url: 'wear_equip', id: inventoryId })
    }
  }

  spawn = (name = 'mouse', num = 1) => {
    const ws = this.props.ws
    ws.mySend({ url: 'spawn', name, num })
  }

  requestEquipDetail = (id) => {
    const ws = this.props.ws
    ws.mySend({url: 'equip', id})
  }

  takeOffEquip = id => {
    const ws = this.props.ws
    ws.mySend({url: 'take_off', id})
  }

  render = () => {
    var main
    const showing = this.state.showing
    const me = this

    if (showing == 0) {
      main = (<Map attack={this.attack} player={this.state.status} move={this.move} map={this.state.map} />)
    } else if (showing == 1) {
      main = (<Status status={this.state.status} equiping={this.state.equiping} detail={this.state.detail} requestEquipDetail={this.requestEquipDetail} takeOffEquip={this.takeOffEquip} />)
    } else if (showing == 2) {
      main = (<div><Inventory wear={thingId => {me.useThing('equip', thingId)}} useItem={thingId => {me.useThing('item', thingId)}} detail={this.state.detail} inventory={this.state.inventory} /></div>)
    } else {
      main = (<div>未知状态</div>)
    }

    return (

      <div className="game">
        <div className="main">
          <div><a href="#" onClick={() => { this.setState({ showing: 0 }) }}>地图</a> <a href="#" onClick={() => { this.setState({ showing: 1 }) }}>状态</a> <a href="#" onClick={() => { this.setState({ showing: 2 }) }}>物品栏</a> </div>
          <br />
          {main}
        </div>

        <div className='log'>
          <this.Log log={this.state.log} />
        </div>

        <button onClick={() => { this.spawn('mouse', 3) }}>Spawn mouse</button>

      </div>
    )
  }
}
